package org.noootsab.gae.games.tzaar.model;

import com.google.appengine.api.datastore.*;
import com.google.appengine.api.datastore.Key;
import org.noootsab.gae.games.tzaar.service.*;

import javax.jdo.*;
import javax.jdo.annotations.*;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * User: sandy
 * Date: 13-mars-2010
 * Time: 22:09:02
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Game implements Externalizable {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    @Unique
    @Column(allowsNull = "false")
    private String gameId;

    @Persistent
    private Boolean started;

    @Persistent
    private Boolean finished;

    @Persistent
    private List<Key> players;

    @Persistent
    private Boolean winnerBlack = null;

    @Persistent
    private Text boardConfigurationJsonText;

    @Persistent
    private Text gameStateJsonText;

    public Game() {
        gameId = UUID.randomUUID().toString();
        players = new ArrayList<Key>();
        started = false;
        finished = false;
    }

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public String getGameId() {
        return gameId;
    }

    public void setGameId(String gameId) {
        this.gameId = gameId;
        setKey(KeyFactory.createKey(Game.class.getSimpleName(), gameId));
    }

    public List<Key> getPlayers() {
        return players;
    }

    public void setPlayers(List<Key> players) {
        this.players = players;
    }

    public Boolean isStarted() {
        return started;
    }

    public void setStarted(Boolean started) {
        this.started = started;
    }

    public Boolean isFinished() {
        return finished;
    }

    public void setFinished(Boolean finished) {
        this.finished = finished;
    }

    public Text getBoardConfigurationJsonText() {
        return boardConfigurationJsonText;
    }

    public void setBoardConfigurationJsonText(Text boardConfigurationJsonText) {
        this.boardConfigurationJsonText = boardConfigurationJsonText;
    }

    public Text getGameStateJsonText() {
        return gameStateJsonText;
    }

    public void setGameStateJsonText(Text gameStateJsonText) {
        this.gameStateJsonText = gameStateJsonText;
    }

    public Boolean isWinnerBlack() {
        return winnerBlack;
    }

    public void setWinnerBlack(Boolean winnerBlack) {
        this.winnerBlack = winnerBlack;
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        String s = (String) in.readObject();
        if (s != null) {
            key = KeyFactory.stringToKey(s);
        }

        gameId = (String) in.readObject();

        started = (Boolean) in.readObject();

        finished = (Boolean) in.readObject();

        winnerBlack = (Boolean) in.readObject();

        List<String> playersStringList = (List<String>) in.readObject();
        if (playersStringList != null) {
            players = new ArrayList<Key>();
            for (String string : playersStringList) {
                if (string != null) {
                    players.add(KeyFactory.stringToKey(string));
                } else {
                    players.add(null);
                }
            }
        }

        s = (String) in.readObject();
        if (s != null) {
            boardConfigurationJsonText = new Text(s);
        }

        s = (String) in.readObject();
        if (s != null) {
            gameStateJsonText = new Text(s);
        }
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        if (key != null) {
            out.writeObject(KeyFactory.keyToString(key));
        }

        out.writeObject(gameId);

        if (players != null) {
            List<String> playersStringList = new ArrayList<String>();
            for (Key k : players) {
                if (k == null) {
                    playersStringList.add(null);
                } else {
                    playersStringList.add(KeyFactory.keyToString(k));
                }
            }
            out.writeObject(playersStringList);
        }

        if (finished) {
            PersistenceManager persistenceManager = PersistenceManagerFactoryHelper.get().getPersistenceManager();
            Player winner = persistenceManager.getObjectById(Player.class, finished&&winnerBlack?players.get(1):players.get(0));
            out.writeObject(winner);
        } else {
            out.writeObject(null);
        }

        if (boardConfigurationJsonText != null) {
            out.writeObject(boardConfigurationJsonText.getValue());
        } else {
            out.writeObject(null);
        }

        if (gameStateJsonText != null) {
            out.writeObject(gameStateJsonText.getValue());
        } else {
            out.writeObject(null);
        }
    }
}